import { resolve, join } from 'path'
import { readFile, access, writeFile } from 'fs/promises'
import { BASE_DIR } from '../config.js'

interface N8nNodeInfo {
  name: string
  displayName: string
  type: string
  category?: string[]
  version: number
  description: string
  filePath: string
}

interface N8nNodeDetails extends N8nNodeInfo {
  properties?: any[]
  inputs?: string[]
  outputs?: string[]
  credentials?: string[]
  usableAsTool?: boolean
}

interface NodePackageInfo {
  name: string
  version: string
  n8n: {
    nodes: string[]
    credentials: string[]
  }
}

interface NodeMetadata {
  version: string
  generatedAt: string
  nodeCount: number
  nodes: N8nNodeDetails[]
}

class N8nNodeIntrospection {
  private nodeCache = new Map<string, N8nNodeDetails>()
  private nodeListCache: N8nNodeInfo[] | null = null
  private packagePath: string
  private metadataPath: string
  private useMetadata: boolean = true

  constructor() {
    // 获取n8n-nodes-base包的路径
    this.packagePath = resolve(BASE_DIR, 'node_modules', 'n8n-nodes-base')
    this.metadataPath = resolve(BASE_DIR, 'src/n8n/node-metadata.json')
  }

  /**
   * 获取所有节点类型列表
   */
  async listNodeTypes(options: { category?: string, search?: string } = {}): Promise<{
    nodes: N8nNodeInfo[]
    total: number
  }> {
    if (!this.nodeListCache) {
      await this.loadNodeData()
    }

    let filteredNodes = this.nodeListCache || []

    // 按类别过滤
    if (options.category) {
      filteredNodes = filteredNodes.filter(node => 
        node.category?.includes(options.category!)
      )
    }

    // 按名称搜索
    if (options.search) {
      const searchLower = options.search.toLowerCase()
      filteredNodes = filteredNodes.filter(node =>
        node.name.toLowerCase().includes(searchLower) ||
        node.displayName.toLowerCase().includes(searchLower)
      )
    }

    return {
      nodes: filteredNodes,
      total: filteredNodes.length
    }
  }

  /**
   * 获取特定节点的详细信息
   */
  async getNodeDetails(nodeType: string): Promise<N8nNodeDetails | null> {
    // 检查缓存
    if (this.nodeCache.has(nodeType)) {
      return this.nodeCache.get(nodeType)!
    }

    try {
      // 如果使用预生成的元数据，直接从缓存中查找
      if (this.useMetadata) {
        await this.loadNodeData()
        // 从缓存中查找
        for (const cachedNode of this.nodeCache.values()) {
          if (cachedNode.name === nodeType || cachedNode.type === nodeType) {
            return cachedNode
          }
        }
        return null
      }
      
      // 先获取节点列表以找到对应的文件路径
      const nodeList = await this.listNodeTypes()
      const nodeInfo = nodeList.nodes.find(node => 
        node.name === nodeType || node.type === nodeType
      )

      if (!nodeInfo) {
        return null
      }

      // 动态加载节点模块
      const modulePath = resolve(this.packagePath, nodeInfo.filePath)
      const nodeModule = require(modulePath)
      
      // 获取节点类（通常是导出的主类）
      const firstKey = Object.keys(nodeModule)[0] || ''
      const NodeClass = firstKey ? nodeModule[firstKey] : null
      
      if (!NodeClass) {
        throw new Error(`无法找到节点类 ${nodeType}`)
      }

      // 创建节点实例以获取description
      let nodeInstance: any;
      let description: any;
      
      try {
        nodeInstance = new NodeClass()
        description = nodeInstance.description
      } catch (error) {
        // 如果无法实例化，尝试直接访问类的静态属性
        description = NodeClass.description || NodeClass.prototype?.description
      }
      
      if (!description) {
        throw new Error(`无法找到节点 ${nodeType} 的description属性`)
      }

      const nodeDetails: N8nNodeDetails = {
        ...nodeInfo,
        properties: description.properties || [],
        inputs: description.inputs?.map((input: any) => input.type || input) || [],
        outputs: description.outputs?.map((output: any) => output.type || output) || [],
        credentials: description.credentials || [],
        usableAsTool: description.usableAsTool || false
      }

      // 缓存结果
      this.nodeCache.set(nodeType, nodeDetails)
      return nodeDetails

    } catch (error) {
      console.error(`加载节点 ${nodeType} 失败:`, error)
      return null
    }
  }

  /**
   * 加载节点数据（优先使用元数据文件，不存在时自动生成）
   */
  private async loadNodeData(): Promise<void> {
    try {
      // 尝试加载预生成的元数据
      await access(this.metadataPath)
      await this.loadFromMetadata()
      console.error('✅ 从元数据文件加载节点信息')
      return
    } catch (error) {
      console.error('⚠️ 元数据文件不存在，开始自动生成...')
      await this.generateMetadata()
      // 生成完成后，重新加载
      await this.loadFromMetadata()
    }
  }

  /**
   * 从预生成的元数据文件加载
   */
  private async loadFromMetadata(): Promise<void> {
    try {
      const metadataContent = await readFile(this.metadataPath, 'utf-8')
      const metadata: NodeMetadata = JSON.parse(metadataContent)
      
      // 加载节点列表
      this.nodeListCache = metadata.nodes.map(node => ({
        name: node.name,
        displayName: node.displayName,
        type: node.type,
        category: node.category,
        version: node.version,
        description: node.description,
        filePath: node.filePath
      }))
      
      // 加载节点详情到缓存
      for (const node of metadata.nodes) {
        this.nodeCache.set(node.name, node)
        if (node.type !== node.name) {
          this.nodeCache.set(node.type, node)
        }
      }
      
      console.error(`✅ 从元数据加载了 ${metadata.nodeCount} 个节点 (生成于 ${metadata.generatedAt})`)
    } catch (error) {
      throw new Error(`加载元数据文件失败: ${error}`)
    }
  }

  /**
   * 从 package.json加载节点列表（实时解析模式）
   */
  private async loadNodeList(): Promise<void> {
    try {
      const packageJsonPath = join(this.packagePath, 'package.json')
      const packageContent = await readFile(packageJsonPath, 'utf-8')
      const packageInfo: NodePackageInfo = JSON.parse(packageContent)

      const nodes: N8nNodeInfo[] = []

      for (const nodePath of packageInfo.n8n.nodes) {
        try {
          const nodeInfo = this.extractNodeInfoFromPath(nodePath)
          if (nodeInfo) {
            nodes.push(nodeInfo)
          }
        } catch (error) {
          console.warn(`解析节点路径失败: ${nodePath}`, error)
        }
      }

      this.nodeListCache = nodes
    } catch (error) {
      console.error('加载n8n节点列表失败:', error)
      this.nodeListCache = []
    }
  }

  /**
   * 从文件路径提取节点基本信息
   */
  private extractNodeInfoFromPath(filePath: string): N8nNodeInfo | null {
    // 解析路径: dist/nodes/ActionNetwork/ActionNetwork.node.js
    const pathParts = filePath.split('/')
    
    if (pathParts.length < 3 || !filePath.endsWith('.node.js')) {
      return null
    }

    const fileName = pathParts[pathParts.length - 1] || ''
    const nodeDir = pathParts[pathParts.length - 2] || ''
    
    // 提取节点名称（去掉.node.js后缀）
    const nodeName = fileName.replace('.node.js', '')
    
    // 尝试从文件名推断显示名称
    const displayName = nodeName
      .replace(/([A-Z])/g, ' $1')
      .replace(/^./, str => str.toUpperCase())
      .trim()

    return {
      name: nodeName,
      displayName,
      type: nodeName,
      version: 1, // 默认版本，实际版本需要从模块中获取
      description: `${displayName} node`,
      filePath,
      category: [this.inferCategory(nodeDir || '')]
    }
  }

  /**
   * 根据目录名推断节点类别
   */
  private inferCategory(dirName: string): string {
    // 可以根据需要扩展类别映射
    const categoryMap: Record<string, string> = {
      'Aws': 'cloud',
      'Google': 'cloud', 
      'Microsoft': 'cloud',
      'Discord': 'communication',
      'Slack': 'communication',
      'Email': 'communication',
      'Http': 'core',
      'Code': 'core',
      'DateTime': 'core'
    }

    return categoryMap[dirName] || 'other'
  }

  /**
   * 自动生成节点元数据文件
   */
  private async generateMetadata(): Promise<void> {
    console.error('🚀 开始自动生成n8n节点元数据...');
    const startTime = Date.now();

    try {
      // 先加载节点列表
      await this.loadNodeList();
      const nodeList = this.nodeListCache || [];
      
      console.error(`📋 发现 ${nodeList.length} 个节点，开始解析详情...`);
      
      const nodeDetails: N8nNodeDetails[] = [];
      let successCount = 0;
      let failedCount = 0;
      
      // 批量解析节点详情
      for (let i = 0; i < nodeList.length; i++) {
        const node = nodeList[i];
        
        // 检查节点是否有效
        if (!node) {
          failedCount++;
          continue;
        }
        
        // 显示进度（每50个节点输出一次）
        if (i % 50 === 0 || i === nodeList.length - 1) {
          process.stderr.write(`\r处理进度: ${i + 1}/${nodeList.length} (${((i + 1) / nodeList.length * 100).toFixed(1)}%)`);
        }
        
        try {
          const details = await this.parseNodeDetails(node);
          if (details) {
            nodeDetails.push(details);
            successCount++;
          } else {
            failedCount++;
          }
        } catch (error) {
          failedCount++;
          // 静默处理失败的节点
        }
      }
      
      console.error(`\n✅ 成功解析 ${successCount} 个节点，失败 ${failedCount} 个`);
      
      // 生成元数据
      const metadata: NodeMetadata = {
        version: '1.0.0',
        generatedAt: new Date().toISOString(),
        nodeCount: nodeDetails.length,
        nodes: nodeDetails
      };
      
      // 写入文件
      await writeFile(this.metadataPath, JSON.stringify(metadata, null, 2));
      
      const endTime = Date.now();
      const duration = ((endTime - startTime) / 1000).toFixed(1);
      
      console.error(`✅ 元数据已自动生成: ${this.metadataPath}`);
      console.error(`📊 耗时: ${duration}秒，文件大小: ${(JSON.stringify(metadata).length / 1024 / 1024).toFixed(2)}MB`);
      
    } catch (error) {
      console.error('❌ 自动生成元数据失败:', error);
      // 生成失败时，fallback到实时解析模式
      this.useMetadata = false;
      await this.loadNodeList();
    }
  }

  /**
   * 解析单个节点的详细信息
   */
  private async parseNodeDetails(nodeInfo: N8nNodeInfo): Promise<N8nNodeDetails | null> {
    try {
      // 动态加载节点模块
      const modulePath = resolve(this.packagePath, nodeInfo.filePath);
      const nodeModule = require(modulePath);
      
      // 获取节点类（通常是导出的主类）
      const firstKey = Object.keys(nodeModule)[0] || '';
      const NodeClass = firstKey ? nodeModule[firstKey] : null;
      
      if (!NodeClass) {
        return null;
      }

      // 创建节点实例以获取description
      let description: any;
      
      try {
        const nodeInstance = new NodeClass();
        description = nodeInstance.description;
      } catch (error) {
        // 如果无法实例化，尝试直接访问类的静态属性
        description = NodeClass.description || NodeClass.prototype?.description;
      }
      
      if (!description) {
        return null;
      }

      return {
        ...nodeInfo,
        properties: description.properties || [],
        inputs: description.inputs?.map ? description.inputs.map((input: any) => input.type || input) : [],
        outputs: description.outputs?.map ? description.outputs.map((output: any) => output.type || output) : [],
        credentials: description.credentials || [],
        usableAsTool: description.usableAsTool || false
      };
      
    } catch (error) {
      return null;
    }
  }

  /**
   * 清空缓存（包括删除元数据文件）
   */
  clearCache(): void {
    this.nodeCache.clear()
    this.nodeListCache = null
  }

  /**
   * 删除元数据文件以强制重新生成
   */
  async clearMetadata(): Promise<void> {
    try {
      const { unlink } = await import('fs/promises');
      await unlink(this.metadataPath);
      console.error('✅ 元数据文件已删除，下次启动将重新生成');
    } catch (error) {
      // 文件不存在时忽略错误
      console.error('ℹ️ 元数据文件不存在或删除失败');
    }
    this.clearCache();
  }
}

// 导出类和类型
export default N8nNodeIntrospection
export type { N8nNodeInfo, N8nNodeDetails, NodeMetadata }
